package cn.kgc.controller;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.DesensitizedUtil;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.core.util.ReUtil;
import cn.kgc.base.BaseInfoProperties;
import cn.kgc.entity.Users;
import cn.kgc.excpetion.GraceException;
import cn.kgc.form.LoginOrRegisterForm;
import cn.kgc.grace.result.GraceJSONResult;
import cn.kgc.grace.result.ResponseStatusEnum;
import cn.kgc.message.SmsMessage;
import cn.kgc.service.UsersService;
import cn.kgc.util.MessageInfoSender;
import cn.kgc.utils.JwtUtil;
import cn.kgc.utils.SmsSenderRetry;
import cn.kgc.vo.UsersVO;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiOperation;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import java.util.concurrent.TimeUnit;

import static cn.kgc.base.SystemConstant.LOGIN_TYPE_APP;

/**
 * @author YC
 */
@RestController
@RequestMapping("/passport")
@Api(tags = "用户认证")
@Validated
public class PassportController extends BaseInfoProperties {

    @Resource
    private UsersService usersService;
    @Resource
    private JwtUtil jwtUtil;
    @Resource
    private MessageInfoSender messageInfoSender;
    @Resource
    private SmsSenderRetry smsSenderRetry;
//    @Resource
//    private SmsSender smsSender;

    @GetMapping("/sendCode")
    @ApiOperation(value = "发送验证码")
    @ApiImplicitParam(name = "phoneNum", value = "手机号码", required = true, dataType = "String")
    public GraceJSONResult sendPhoneCode(String phoneNum) {
        // 判断手机号格式是否正确
        boolean verify = ReUtil.isMatch("^1[3456789]\\d{9}$", phoneNum);
        if (!verify) {
            GraceException.display(ResponseStatusEnum.SMS_PHONE_ERROR);
        }
        // 判断60s内是否发送过验证码，true返回错误信息（判断Redis中是否有信息）,false生成6位手机验证码，调用短信服务API发送验证码到用户手机上，并保存到Redis中TTL60s
        // TODO 可选：用户发送验证码收不到，60s内换个Ip地址重新发送（将Ip信息保存到Redis中）
        String key = MOBILE_SMSCODE + phoneNum;
        String randomCode = RandomUtil.randomNumbers(6);
        boolean result = redisUtil.setIfAbsent(key, randomCode, 300, TimeUnit.SECONDS);
        if (!result) {
            GraceException.display(ResponseStatusEnum.SMS_NEED_WAIT_ERROR);
        }
        try {
//            smsSender.sendMsg(phoneNum, randomCode);
//            System.out.println("模拟短信已发送！在接口返回值中查看");  // 第三方接口短信发送需要RMB，print模拟第三方发送短信
            smsSenderRetry.sendSms(phoneNum, randomCode);  // 模拟短信发送错误重试三次之后依然异常才返回异常信息
        } catch (Exception e) {
            GraceException.display(ResponseStatusEnum.MOBILE_ERROR);
        }
        // 进入组件RabbitMQ消息队列（封装版）
        SmsMessage smsMessage = new SmsMessage();
        smsMessage.setPhoneNumber(phoneNum);
        smsMessage.setCode(randomCode);
        //
        messageInfoSender.sendMessage("smsExchange", "smsRoutingKey", smsMessage);
        return GraceJSONResult.ok("验证码：" + randomCode);
    }

    @PostMapping("/loginOrRegister")
    @ApiOperation(value = "一键登录或注册")
    public GraceJSONResult loginOrRegister(@Validated @RequestBody LoginOrRegisterForm form) {
        // 判断手机验证码是否正确
        String key = MOBILE_SMSCODE + form.getMobile();
        if (!form.getSmsCode().equals(redisUtil.get(key))) {
            GraceException.display(ResponseStatusEnum.SMS_CODE_ERROR);
        }
        // 判断用户是否已经注册，已经注册则直接登录，未注册则注册用户并登录（业务层接口）
        Users users = usersService.login(form.getMobile());
        if (users == null) {
            users = usersService.registerAndInitResume(form.getMobile());
        }
        // 删除Redis中的验证码
        redisUtil.delete(key);
        // 生成登录令牌，将用户信息和登录令牌返回
        String token = jwtUtil.createToken(users.getId(), LOGIN_TYPE_APP);
        UsersVO usersVo = BeanUtil.copyProperties(users, UsersVO.class);
        usersVo.setToken(token);
        // 可选：手机号脱敏
        usersVo.setMobile(DesensitizedUtil.mobilePhone(users.getMobile()));
        return GraceJSONResult.ok(usersVo);
    }

}